#pragma once
#include<iostream>
#include<vector>
#include<time.h>
#include<assert.h>
#include <windows.h>
#include <cstdio>
#include<assert.h>
#include<unordered_map>
#include<thread>
#include"ObjectPool.h"
#include<mutex>
#include<unistd.h>
using std::cout;
using std::endl;
using std::vector;
class ThreadCache;
extern vector<int> Indexsgroup; 
// 1. 最大字节数
inline constexpr size_t MAX_BYTEs = 256 * 1024;   // 256 KB
inline constexpr size_t MAX_FREELIST = 208;   // 256 KB
inline constexpr size_t MAX_SPANS = 129;   // 128*8kb=1024KB
inline constexpr size_t PAGE_SHIFT = 13;   // 8k

#ifdef _WIN64
    typedef uint64_t PageID;
#elif _WIN32
    typedef size_t PageID;
#endif //_WIN32
//计算对象大小映射规则：
class Sizeclass{
// [1,128] 8byte对齐 freelist[0,16)
// [128+1,1024] 16byte对齐 freelist[16,72)
// [1024+1,8*1024] 128byte对齐 freelist[72,128)
// [8*1024+1,64*1024] 1024byte对齐 freelist[128,184)
// [64*1024+1,256*1024] 8*1024byte对齐 freelist[184,208)
private:
    static inline size_t _Roundup(size_t size,size_t AlignNUM){
        return (size+(AlignNUM-1))&~(AlignNUM-1);//向上对齐到AlignNUM的整数倍
    }
    static inline size_t _Index(size_t bytes,size_t AlignNUM){
        if(bytes%AlignNUM==0)return bytes/AlignNUM;
        else return bytes/AlignNUM+1;
    }
    
public:
    static inline size_t reoundUp(size_t size){
        if(size<=128){
           return _Roundup(size,8);
        }
        else if(size<=1024){
            return _Roundup(size,16);
        }
        else if(size<=8*1024){          
            return _Roundup(size,128);
        }
        else if(size<=64*1024){
           return _Roundup(size,1024);
        }
        else if(size<=256*1024){
           return _Roundup(size,8*1024);
        }
        else{
            return _Roundup(size,1<<PAGE_SHIFT);
        }
    } 
    static inline size_t Index(size_t size){
       if(size<=128){
           return _Index(size,8)+Indexsgroup[0];
        }
        else if(size<=1024){
           return _Index(size-128,16)+Indexsgroup[1];
        }
        else if(size<=8*1024){
            return _Index(size-1024,1024)+Indexsgroup[2]; 
        }
        else if(size<=64*1024){
           return _Index(size-8*1024,8*1024)+Indexsgroup[3];
        }
        else if(size<=256*1024){
           return _Index(size-64*1024,256*1024)+Indexsgroup[4];
        }
        else{
            assert(false);
            return -1;
        }
    }
     static size_t NumMoveSize(size_t size){
            assert(size>0&&size<=MAX_BYTEs);
            int num=MAX_BYTEs/size;
            if(num<2)num =2;
            if(num>512)num=512;
            return num;
        }
    static size_t NumMovePage(size_t size){
        //我要N个size大小的地方
        size_t num=Sizeclass::NumMoveSize(size);
        size_t npage=num*size;
        //一个page是8k，右移13位就是页数
        npage>>=PAGE_SHIFT;
        if(npage<1)npage=1;
        if(npage>MAX_SPANS)npage=MAX_SPANS;
        return npage;
    }
 };
//管理切分好的小对象
//  声明只留这一行，定义放到 Common.cc
void*& NextObj(void* obj);
class FreeList{
    public:
        void *Push(void *obj){
            //头插
            //取前面4/8个字节void*大小，存放指针
            //(void**)obj 做了什么？
            // 这是类型转换，不是内存操作。
            // 你把 obj 的值（一个地址）重新解释为 void** 类型。
            // 也就是说，你现在告诉编译器：
            // “这个地址，其实指向的是一个 void* 变量。”
            // 注意：这不是创建了一个新的指针，而是重新解释了原来的地址。
            //  *(void**)obj 做了什么？
            // 这是解引用操作。
            // 你现在有一个 void** 类型的指针，它指向某个内存位置。
            // 你解引用它，就是从那个内存位置读取 sizeof(void*) 个字节，并解释为一个 void* 类型的值。
            // 内存视角：到底发生了什么？
            // 假设：
            // 你是在 64 位系统上，sizeof(void*) == 8。
            // obj 的值是 0x1000，即它指向地址 0x1000。
            // 地址 0x1000 开始的 8 个字节内容是：
            NextObj(obj) = _freeList;
            _freeList= obj;
            ++_size;
            return obj;   // 原代码缺少返回值，补上
        }
        void *Pop(){
            //头删
            assert(_freeList);
            void*obj=_freeList;
            _freeList=NextObj(obj);
            --_size;
            return obj;   
        }
        bool Empty(){
            return _freeList==nullptr;
        }
        size_t& MaxSize(){
            return maxSize;
        }
        void Pushrange(void*start,void*end,size_t n){
            assert(start);
            assert(end);
            NextObj(end)=_freeList;
            
            _size+=n;
            _freeList=start;
        }
        void PopRange(void*start,void*end,size_t n){
            assert(n<=_size);
            end=start=_freeList;
            for(size_t i=0;i<n-1;i++){
                end=NextObj(end);
            }
            _freeList=NextObj(end);
            _size-=n;
        }
        size_t Size(){
            return _size;
        }
    private:
        void *_freeList=nullptr;//头节点
        size_t maxSize=1;
        size_t _size=0;

};
//管理多个页的跨度结构
//2^32/2^13=2^19页 32位系统
//2^64/2^13=2^46页 64位系统
struct Span{
    PageID _pageID=0;//页号
    size_t _n=0;//页数量
    Span* _next=nullptr;
    Span* _prev=nullptr;
    void* _freelist=nullptr;//切好的小块内存的链表
    size_t _usecount=0;//切好的小块内存的使用计数
    size_t _objsize=0;//对象大小
    bool _isUse=false;//是否在使用
};
//带头双向循环链表
class SpanList{
   public:
      SpanList(){
        _head=new Span;
        _head->_next=_head;
        _head->_prev=_head;
      }
      Span*Begin(){
        //带头双向循环
        return _head->_next;
      }
      Span*End(){
        return _head;
      }
      void Insert(Span*pos,Span*newSpan){
        //头插
        assert(pos);
        assert(newSpan);
        Span*prev=pos->_prev;
        prev->_next=newSpan;
        newSpan->_prev=prev;
        newSpan->_next=pos;
        pos->_prev=newSpan;
      }
      void Erase(Span*pos){
        assert(pos);
        assert(pos!=_head);
        Span*prev=pos->_prev;
        Span*next=pos->_next;
        prev->_next=next;
        next->_prev=prev;
        pos->_next=nullptr;
        pos->_prev=nullptr;
      }
      void PushFront(Span*newSpan){
        //头插
        Insert(_head->_next,newSpan);
      }
      bool Empty(){
        return _head->_next==_head;
      }
      Span* PopFront(){
       Span*pos=_head->_next;
        //头删
        Erase(_head->_next);
        return pos;
      }
       private:
   Span *_head;
   public:
   std::mutex _mtx;
};